<template>
  <div class="table-design">
    <je-panel v-bind="lauoutOptions">
      <template #left>
        <!-- Tree开始 -->
        <je-tree
          ref="treeview"
          class="view-treeView"
          :search="{ style: 'height:40px;' }"
          :tree-config="{
            trigger: 'cell-dblclick',
            rowField: 'id',
            parentField: 'parent',
          }"
          size="mini"
          :data="treeData"
          @cell-dblclick="handlerSelect"
        >
          <template #nodeIcon="{ row }">
            <span
              v-if="
                row.bean.RESOURCETABLE_CHILDTABLECODES != undefined &&
                row.bean.RESOURCETABLE_CHILDTABLECODES != ''
              "
              class="beforesign"
            ></span>
            <span
              v-if="
                row.bean.RESOURCETABLE_PARENTTABLECODES != undefined &&
                row.bean.RESOURCETABLE_PARENTTABLECODES != ''
              "
              class="aftersign"
            >
            </span>
            <template v-if="row.nodeInfo === 'MODULE'">
              <i style="color: #ffba3d" class="fas fa-folder"></i>
            </template>
            <template v-else-if="row.nodeInfo === 'PT'">
              <i
                :style="`color: ${row.bean.RESOURCETABLE_IMPORT == '1' ? '#333333' : '#3265F5'}`"
                class="jeicon jeicon-table"
              ></i>
            </template>
            <template v-else-if="row.nodeInfo === 'TREE'">
              <i
                :style="`color: ${row.bean.RESOURCETABLE_IMPORT == '1' ? '#333333' : '#D70028'}`"
                class="jeicon jeicon-treetable"
              ></i>
            </template>
            <template v-else-if="row.nodeInfo === 'VIEW'">
              <i
                :style="`color: ${row.bean.RESOURCETABLE_IMPORT == '1' ? '#333333' : '#F59B22'}`"
                class="jeicon jeicon-process"
              ></i>
            </template>
          </template>
          <template #bbar>
            <div class="treebottom-context">
              <div class="context">双击使用</div>
            </div>
          </template>
        </je-tree>
        <!-- Tree结束 -->
      </template>
      <template #tbar>
        <div class="design-title top">{{ $t('viewModal.TabDesignTitle') }}</div>
      </template>
      <template #default>
        <div id="diagramContainer">
          <div
            v-if="designTableDatas.length <= 0"
            style="position: absolute; top: 30%; left: 25%; font-size: 18px; color: A9ABA9"
            >请双击选择左侧资源表进行编辑视图</div
          >
          <DesignTable
            v-for="data in designTableDatas"
            v-else
            :key="data.tableId"
            :tabel-datas="data"
            :plumb-ins="plumbIns"
            class="item"
            @monitorDelete="monitorDelete"
            @checkChange="checkChange"
          ></DesignTable>
        </div>
      </template>
    </je-panel>
  </div>
</template>

<script>
  import { defineComponent, ref, onMounted, watch, reactive, nextTick } from 'vue';
  import { Tree, Panel, Modal } from '@jecloud/ui';
  import { isNotEmpty } from '@jecloud/utils';
  import { getTree, doUpdate } from '../../api/index';
  import { jsPlumb } from 'jsplumb';
  import DesignTable from './design-table.vue';
  import VueEvent from '../../helper/model/event';

  export default defineComponent({
    name: 'DesignView',
    components: {
      JePanel: Panel,
      JeTree: Tree,
      DesignTable,
    },
    props: {
      designDatas: {
        type: Object,
        requied: true,
        default: () => {
          return {};
        },
      },
      tableId: {
        type: String,
        requied: true,
        default: '',
      },
      productData: {
        type: Object,
        required: true,
        default: () => {
          return {};
        },
      },
    },
    emits: ['changeDatas', 'chageCheckData'],
    setup(props, { emit }) {
      const plumbIns = ref(jsPlumb.getInstance());

      //tabel数据
      const designTableDatas = ref([]);

      //回显表格数据
      watch(
        () => props.designDatas.tableDatas,
        (newVal) => {
          designTableDatas.value = newVal;
          nextTick(() => {
            designTableDatas.value.forEach((item, index) => {
              document.getElementById(item.tableId).style.left = item.left;
              document.getElementById(item.tableId).style.top = item.top;
              plumbIns.value.draggable(item.tableId, {
                containment: 'diagramContainer',
                stop: function (e) {
                  // 拖拽后改变位置,修改本地数据
                  saveRealLocation(e.el);
                },
              });
            });
          });
        },
      );
      //拖拽table面板实时保存位置
      const saveRealLocation = (el) => {
        const viewId = el.id;
        const viewTop = el.style.top;
        const viewLeft = el.style.left;
        const dataArray = [];
        designTableDatas.value.forEach((item) => {
          if (item.tableId == viewId) {
            item.top = viewTop;
            item.left = viewLeft;
          }
          if (item.left && item.top) {
            dataArray.push(item);
          }
        });
        dataArray.forEach((item) => {
          item.queryType && delete item.queryType;
          item.selectCode && delete item.selectCode;
          item.searchValue && delete item.searchValue;
        });
        if (dataArray.length > 0) {
          doUpdate({
            tableCode: 'JE_CORE_RESOURCETABLE',
            JE_CORE_RESOURCETABLE_ID: props.tableId,
            RESOURCETABLE_COORDINATE: JSON.stringify(dataArray),
          })
            .then((data) => {})
            .catch((e) => {
              Modal.alert(e.message, 'error');
            });
        }
      };
      //回显连线
      watch(
        () => props.designDatas.lineinfo,
        (newVal) => {
          nextTick(() => {
            newVal.forEach((item) => {
              changeLine(item);
            });
          });
        },
      );

      //处理 tree 的数据
      const treeData = ref([]);
      onMounted(() => {
        getTreeData();
        nextTick(() => {
          showPlumb();
        });
      });
      //获得Tree的数据
      const getTreeData = () => {
        const params = {
          tableCode: 'JE_CORE_RESOURCETABLE',
          excludes: 'checked',
          node: 'ROOT',
          j_query: JSON.stringify({
            order: [{ code: 'SY_ORDERINDEX', type: 'ASC' }],
            custom: [
              {
                type: 'and',
                value: [
                  { code: 'RESOURCETABLE_ISCREATE', type: '=', value: '1', cn: 'or' },
                  { code: 'RESOURCETABLE_TYPE', type: '=', value: 'MODULE', cn: 'or' },
                ],
              },
            ],
          }),
          SY_PRODUCT_ID: props.productData.productId,
        };
        //params.SY_PRODUCT_ID = props.productData.productId;
        getTree(params)
          .then((data) => {
            treeData.value = data.children;
          })
          .catch((e) => {
            Modal.alert(e.message, 'error');
          });
      };
      //tree选中
      const handlerSelect = ({ row }) => {
        if (row.nodeInfo != 'MODULE') {
          addViewTable(row);
        }
      };
      //初始化jsplumb插件
      const showPlumb = () => {
        plumbIns.value.ready(() => {
          //默认设置
          plumbIns.value.importDefaults({
            PaintStyle: { stroke: '#909399', strokeWidth: 2 },
            Connector: ['Straight'],
            Container: 'diagramContainer', //选择器id
            Endpoint: 'Blank',
            EndpointStyle: { radius: 0.11, fill: '#999' },
            ConnectionsDetachable: false, // 再次拖动时不取消选择
            maxConnections: 1,
            uniqueEndpoint: true,
            Anchor: [
              'Left',
              'Right',
              'Top',
              'Bottom',
              [0.3, 0, 0, -1],
              [0.7, 0, 0, -1],
              [0.3, 1, 0, 1],
              [0.7, 1, 0, 1],
            ],
          });
        });
      };
      //jsplumb插件修改连线
      const changeLine = (row) => {
        //删除连线
        const connections = plumbIns.value.getAllConnections();
        for (var i in connections) {
          if (
            connections[i].sourceId === row.mainTableId &&
            connections[i].targetId === row.targetTableId
          ) {
            // 删除相匹配的线
            plumbIns.value.deleteConnection(connections[i]); // deleteConnection(@) 删除链接线  @线对象
          }
        }
        //添加连线
        if (row.isDispalyLine) {
          // 先封装label
          const { mainIdentifier, targetIdentifier, mainTableId, targetTableId } = row;
          // 标识A label
          const leftLabel = mainIdentifier ?? '';
          // 标识B label
          const rightLabel = targetIdentifier ?? '';
          // 最终label
          const label = `${leftLabel}${leftLabel && rightLabel ? ':' : ''}${rightLabel}`;
          // 把label放入 location 是label的位置 0.5在中间
          const overlays = [
            ['Label', { label, location: mainTableId == targetTableId ? -40 : 0.5 }],
          ];
          // 封装箭头方向 direction = 1 location=1 右箭头 ,direction = -1 location=0 左箭头
          // 默认是右箭头
          let direction = 1;
          let location = 1;
          // 如果 标识A = n/on 改为左箭头
          if (['n', 'on'].includes(mainIdentifier)) {
            direction = -1;
            location = 0;
          }
          // 如果标识A和标识B的值有一个存在 n/on 就有一个箭头
          if (['n', 'on'].includes(mainIdentifier) || ['n', 'on'].includes(targetIdentifier)) {
            overlays.push(['Arrow', { width: 10, length: 10, location, direction }]);
          }
          // 如果标识A和标识B的值都存在 n/on 就在加一个反向的箭头(双箭头)
          if (['n', 'on'].includes(mainIdentifier) && ['n', 'on'].includes(targetIdentifier)) {
            const newDirection = direction == 1 ? -1 : 1;
            const location = newDirection == 1 ? 1 : 0;
            overlays.push(['Arrow', { width: 10, length: 10, location, direction: newDirection }]);
          }
          // 划线
          if (isNotEmpty(mainTableId) && isNotEmpty(targetTableId)) {
            const defaultConfig = {
              // 对应上述基本概念
              source: mainTableId,
              target: targetTableId,
              overlays: overlays,
            };
            if (mainTableId == targetTableId) {
              defaultConfig['connector'] = ['StateMachine'];
            }
            plumbIns.value.connect(defaultConfig);
          }
        }
      };
      //添加视图列表
      const addViewTable = (node) => {
        //判断table是否存在
        let flag = true;
        for (let index = 0; index < designTableDatas.value.length; index++) {
          if (designTableDatas.value[index].tableId == node.id) {
            flag = false;
            return flag;
          }
        }
        if (flag) {
          let iconCls = 'jeicon jeicon-table';
          if (node.nodeInfo == 'TREE') {
            iconCls = 'jeicon jeicon-treetable';
          } else if (node.nodeInfo == 'VIEW') {
            iconCls = 'jeicon jeicon-process';
          }
          designTableDatas.value.push({
            tableId: node.id,
            tableCode: node.code,
            tableName: node.text,
            iconCls,
            selectCode: [],
          });
          emit('changeDatas', 'concernSelectData', {
            tableCode: node.code,
            tableId: node.id,
            tableName: node.text,
            value: node.code,
            label: node.text,
          });
          //拖拽
          nextTick(() => {
            document.getElementById(node.id).style.left =
              (designTableDatas.value.length - 1) * 40 + 5 + 'px';
            document.getElementById(node.id).style.top = '10px';
            plumbIns.value.draggable(node.id, {
              containment: 'diagramContainer',
              stop: function (e) {
                // 拖拽后改变位置,修改本地数据
              },
            });
          });
        }
      };

      //监听删除table面板
      const monitorDelete = (tableId) => {
        //删除视图设计的table
        designTableDatas.value.forEach((item, index) => {
          if (item.tableId == tableId) {
            designTableDatas.value.splice(index, 1);
          }
        });
        //删除下拉框的数据
        emit('changeDatas', 'delConcernSelectData', {
          tableId: tableId,
        });
        //删除关系设置的数据
        VueEvent.emit('deleteConcernTableData', tableId);
      };

      //监听子组件的table列选中状态
      const checkChange = (obj, records) => {
        emit('chageCheckData', obj, records);
      };

      //监听关系设置的数据变化,改变连线
      VueEvent.on('changeLine', (data) => {
        changeLine(data);
      });
      return {
        plumbIns,
        treeData,
        designTableDatas,
        monitorDelete,
        handlerSelect,
        checkChange,
        lauoutOptions: {
          left: { size: 240, split: true },
          tbar: { size: 40 },
        },
      };
    },
  });
</script>

<style lang="less" scoped>
  .table-design {
    height: 100%;
    .searchInput {
      height: 40px;
      border-color: #e6e6e6 !important;
      border-radius: 0;
    }
    #diagramContainer {
      position: relative;
    }
    .item {
      position: absolute;
      height: 500px;
      width: 400px;
      border-top: 1px solid #e6e6e6;
      border-bottom: 1px solid #e6e6e6;
      z-index: 10;
    }
    .design-title {
      height: 40px;
      background: #f7f9fc;
      line-height: 40px;
      font-size: 14px;
      padding: 0 16px;
      color: #3265f5;
    }
    .design-title.top {
      border-bottom: 1px solid #e6e6e6;
      border-top: 1px solid #e6e6e6;
    }
    /* .design-content {
        height: calc(100vh - 440px);
        padding: 15px 57px 0 32px;
      } */
    .design-table {
      //min-height: 200px;
      height: 100%;
    }
    .beforesign {
      position: relative;
      display: inline-block;
      height: 4px;
      &::before {
        content: '';
        display: inline-block;
        width: 4px;
        height: 4px;
        background: #d70000;
        position: absolute;
        top: -7px;
        left: -6px;
      }
    }
    .aftersign {
      position: relative;
      display: inline-block;
      height: 4px;
      &::after {
        content: '';
        display: inline-block;
        width: 4px;
        height: 4px;
        background: #006ed7;
        position: absolute;
        bottom: -1px;
        left: -6px;
      }
    }
    .treebottom-context {
      font-size: 14px;
      height: 32px;
      line-height: 32px;
      text-align: center;
      margin: 10px;
      .context {
        height: 32px;
        border: 1px solid #a8d09d;
        background: #eff9f2;
        color: #36761f;
      }
    }
  }
</style>
<style lang="less">
  .table-design {
    .ant-input-affix-wrapper.ant-select-selection-search-input:hover {
      border: 1px solid #5c8dff !important;
      box-shadow: none !important;
    }
    .ant-input-affix-wrapper.ant-select-selection-search-input {
      height: 40px !important;
      border-color: #e6e6e6 !important;
      border-radius: 0;
      .ant-input-suffix {
        .anticon.ant-input-clear-icon {
          top: 9px;
        }
      }
    }
    .ant-input-affix-wrapper-focused.ant-select-selection-search-input {
      border: 1px solid #5c8dff !important;
      box-shadow: none !important;
    }
    #diagramContainer {
      position: relative; /*一定加上这句，否则连线位置发生错乱*/
      height: 150%;
      width: 150%;
    }
    .layout-default-wrapper {
      border-right: 1px solid #e6e6e6;
    }
    /* .view-treeView {
      padding: 10px 0;
    } */
    .designView-default.je-border-layout .layout-default {
      overflow-x: auto;
    }
    .je-panel-item-region-bottom {
      border-right: 1px solid #e6e6e6;
    }
  }
</style>
